public class Test {
    public static void main(String[] args) throws Exception {
        VendingMachine vm = new VendingMachine();
        vm.coin(); // 投币
        vm.pass(); // 通过
        vm.back(); // 退币
    }
}

// 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
// 状态模式（State）经常用在带有状态的对象中
/* ---------- 状态接口 ---------- */
interface State {
    void coin();

    void pass();

    void back();
}

/* ---------- 具体状态 ---------- */
class NoCoinState implements State {
    private final VendingMachine vm;

    NoCoinState(VendingMachine vm) {
        this.vm = vm;
    }

    public void coin() {
        System.out.println("已投币");
        vm.setState(vm.getHasCoin());
    }

    public void pass() {
        System.out.println("请先投币");
    }

    public void back() {
        System.out.println("无币可退");
    }
}

class HasCoinState implements State {
    private final VendingMachine vm;

    HasCoinState(VendingMachine vm) {
        this.vm = vm;
    }

    public void coin() {
        System.out.println("已投过币");
    }

    public void pass() {
        System.out.println("出货成功");
        vm.setState(vm.getNoCoin());
    }

    public void back() {
        System.out.println("退币成功");
        vm.setState(vm.getNoCoin());
    }
}

/* ---------- 上下文 ---------- */
class VendingMachine {
    private final State noCoin = new NoCoinState(this);
    private final State hasCoin = new HasCoinState(this);
    private State current = noCoin;

    void coin() {
        current.coin();
    }

    void pass() {
        current.pass();
    }

    void back() {
        current.back();
    }

    void setState(State s) {
        current = s;
    }

    State getNoCoin() {
        return noCoin;
    }

    State getHasCoin() {
        return hasCoin;
    }
}